
package com.eva.android.widget;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Map;

//import net.dmkx.mobi1.R;
import android.app.Activity;
//import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.text.Editable;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.style.ForegroundColorSpan;
import android.util.Log;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

//import com.eva.android.RHolder;
import com.eva.android.widget.alert.AlertDialog;
import com.eva.epc.common.util.DoubleHelper;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.x52im.rbchat.R;
import com.x52im.rbchat.logic.chat_root.model.Message;
import com.x52im.rbchat.logic.search.content.SearchableContent;

/**
 * UI组件实用类.
 * 
 * @author Jack Jiang, 2011-08-20
 * @version 1.0
 */
public class WidgetUtils
{
	private final static String TAG = WidgetUtils.class.getSimpleName();
	
	public final static int TOAST_TYPE_NONE  = 1;  // 00001
	public final static int TOAST_TYPE_OK    = 2;  // 00010
	public final static int TOAST_TYPE_INFO  = 4;  // 00100
	public final static int TOAST_TYPE_WARN  = 8;  // 01000
	public final static int TOAST_TYPE_ERROR = 16; // 10000
	
	public static int toastTypeSurport = 
		TOAST_TYPE_NONE | TOAST_TYPE_OK | TOAST_TYPE_INFO | TOAST_TYPE_WARN | TOAST_TYPE_ERROR;

	/**
	 * 将文本编辑框中的光标移动到末尾。
	 *
	 * @param editView 文本输入框
	 * @since 9.0
	 */
	public static void setCursorToEnd(EditText editView, boolean requestFocus){
		if(editView != null) {
			// 光标移动到尾部
			editView.setSelection(editView.length());
			if(requestFocus){
				// 请求焦点
				editView.requestFocus();
			}
		}
	}

	/**
	 * 动画高亮显示一次消息（动画完成后重置高亮标识）。
	 *
	 * @param messageItemView 聊天界面中的itemView引用
	 * @param message  将要高亮显示的消息对象
	 * @since 8.2
	 */
	public static void highlightOnceMessageItem(Message message, View messageItemView) {

		if(message != null && messageItemView != null) {

			// 立即将数据标识复位，防止重复
			message.setHighlightOnce(false);

			// Alpha动画（让ui组件的ui进行半透明效果变换，0~1值：1表示不透明、0表示全透明）
			Animation animation = new AlphaAnimation(1.0f, 0.1f);
			// 添加动画状态监听器
			animation.setAnimationListener(new Animation.AnimationListener() {
				@Override
				public void onAnimationStart(Animation animation) {
				}

				@Override
				public void onAnimationEnd(Animation animation) {
//					// 数据标识复位
//					message.setHighlightOnce(false);
					// ui显示复位
					messageItemView.setBackground(null);
				}

				@Override
				public void onAnimationRepeat(Animation animation) {
				}
			});
			// 每次动画持续时间（单位：毫秒）
			animation.setDuration(500);
			// 动画重复次数
			animation.setRepeatCount(3);
			// 设置背景
			messageItemView.setBackgroundResource(R.drawable.shape_chatting_msg_higlight_bg);
			// 开始动画
			messageItemView.startAnimation(animation);
		}
	}

	/**
	 * 设置在src中第一次出现的keyword的颜色。
	 *
	 * @param context 上下文对象引用
	 * @param src 原始字符串
	 * @param keyword 关键字
	 * @param keywordColorResId 关键字的颜色资源id
	 * @return 处理好关键字颜色后的字符串对象
	 * @since 8.2
	 */
	public static SpannableStringBuilder coloredStringForSearch(Context context, String src, String keyword, int keywordColorResId){
		SpannableStringBuilder spBuilder = null;
		try {
			if (!TextUtils.isEmpty(src) && !TextUtils.isEmpty(keyword) && src.contains(keyword)) {
				int start = src.indexOf(keyword);
				int end = start + keyword.length();

				spBuilder = new SpannableStringBuilder(src);
				ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(context.getResources().getColor(keywordColorResId));
				spBuilder.setSpan(foregroundColorSpan, start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
			}
		} catch (Exception e){
			Log.w(TAG, e);
		}
		return spBuilder;
	}

	/**
	 * 清除BottomNavigationView组件item长按时的toast提示（那个太丑了）。
	 * 参考资料：https://www.jianshu.com/p/277621b8ccfd
	 *
	 * @param bottomNavigationView BottomNavigationView对象
	 * @param ids 与BottomNavigationView的menu配置文件中对应的所有id（id与配置文件中要绝对一致(包括顺序)）
	 */
	public static void clearBottomNavigationViewToast(BottomNavigationView bottomNavigationView, List<Integer> ids) {
		ViewGroup bottomNavigationMenuView = (ViewGroup) bottomNavigationView.getChildAt(0);
		// 遍历子View,重写长按点击事件
		for (int position =0; position < ids.size(); position++){
			bottomNavigationMenuView.getChildAt(position).findViewById(ids.get(position)).setOnLongClickListener(v -> true);
		}
	}

	/**
	 * 隐藏系统输入法控件。
	 *
	 * @param ac 所属父activity
	 * @param v  焦点所有view对象
	 * @deprecated by {@link com.eva.android.ToolKits#hideInputMethod(Activity, View)} }
	 */
	public static void hideInputMethod(Activity ac, View v) {
		if (ac != null && v != null) {
			try {
				InputMethodManager inputManager = (InputMethodManager) ac.getSystemService(Context.INPUT_METHOD_SERVICE);
				inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
			} catch (Exception e) {
				Log.w(SearchableContent.class.getSimpleName(), e.getMessage(), e);
			}
		}
	}

//	/**
//	 * 显示系统输入法控件。
//	 *
//	 * @param ac 所属父activity
//	 */
//	public static void showInputMethod(Activity ac){
//		if(ac != null) {
//			try {
//				// 弹出输入法
//				ac.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
//			} catch (Exception e) {
//				Log.w(SearchableContent.class.getSimpleName(), e.getMessage(), e);
//			}
//		}
//	}

	/**
	 * 将View对象内容作为内容生成Bitmap对象。
	 *
	 * @param v View对象
	 * @return 如果生成成功则返回bitmap对象，否则返回null
	 * @since 8.0
	 */
	public static Bitmap generateBitmap(View v) {
		Bitmap bmp = null;
		try {
			int w = v.getWidth();
			int h = v.getHeight();

			bmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
			Canvas c = new Canvas(bmp);

			// 如果不设置canvas画布为白色，则生成透明
			c.drawColor(Color.WHITE);

//			v.layout(0, 0, w, h);
			v.draw(c);
		} catch (OutOfMemoryError oom) {
			Log.w(TAG, "从View对象生成Bitmap对象时OOM了！", oom);
		} catch (Exception e) {
			Log.w(TAG, "从View对象生成Bitmap对象失败了！", e);
		}

		return bmp;
	}

	/**
	 * 代码里实现drawLeft图标。
	 *
	 * @param ctx
	 * @param icon_res_id
	 * @param view
	 */
	public static void setDrawLeft(Context ctx, int icon_res_id, TextView view)
	{
		Drawable statusImg = ctx.getResources().getDrawable(icon_res_id);
		statusImg.setBounds(0, 0, statusImg.getMinimumWidth(), statusImg.getMinimumHeight());
		view.setCompoundDrawables(statusImg, null, null, null);
	}

	/**
	 * 代码里实现drawRight图标。
	 *
	 * @param ctx
	 * @param icon_res_id
	 * @param view
	 */
	public static void setDrawRight(Context ctx, int icon_res_id, TextView view)
	{
		Drawable statusImg = ctx.getResources().getDrawable(icon_res_id);
		statusImg.setBounds(0, 0, statusImg.getMinimumWidth(), statusImg.getMinimumHeight());
		view.setCompoundDrawables(null, null, statusImg, null);
	}

	/**
	 * 读取assets目录下文本文件内容
	 * Freeman 2021.4.23添加
	 * @param context
	 * @param filePath               assets文件路径
	 * @return 文件内容字符串
	 */
	public static String readAssetsFileText(Context context, String filePath) {
		String result = "";
		InputStream inputStream = null;
		try {
			inputStream = context.getAssets().open(filePath);
			BufferedReader bfReader = new BufferedReader(new InputStreamReader(inputStream));
			StringBuffer buffer = new StringBuffer();
			String line = " ";
			while ((line = bfReader.readLine()) != null){
				buffer.append(line);
			}
			result = buffer.toString();
		} catch (IOException e) {
			Log.w("readAssetsFileText", e.toString());
		}
		return result;
	}

	/**
	 * 读取assets中的图片
	 * Freeman 2021.4.23添加
	 * @param context context
	 * @param assetPath 图片在assets文件加下的子路径
	 * @param reqWidth
	 * @param reqHeight
	 * @return 位图对象
	 */
	public static Bitmap readAssetsFileBitmap(Context context, String assetPath, int reqWidth, int reqHeight) {
		InputStream is = null;
		try {
			BitmapFactory.Options options = new BitmapFactory.Options();
			is = context.getAssets().open(assetPath);
			if(is != null){
				Bitmap bitmap = BitmapFactory.decodeStream(is, new Rect(), options);
				Log.d("---------表情--","bitmap="+bitmap);
				return bitmap;
			}
		} catch (IOException e) {
			Log.w("readAssetsFileBitmap", e.toString());
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					Log.w("readAssetsFileBitmap", e.toString());
				}
			}
		}
		return null;
	}

	/**
	 * 将dip转换为像素.
	 */
	public static int dip2px(Context context, float dipValue)
	{
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int) (dipValue * scale + 0.5f);
	}
	/**
	 * 将像素转换成dip.
	 *
	 * @param context
	 * @param pxValue
	 * @return
	 */
	public static int px2dip(Context context, float pxValue)
	{
		final float scale = context.getResources().getDisplayMetrics().density;
		return (int)(pxValue / scale + 0.5f);
	}

	/**
	 * 将图片截取为圆角图片
	 * @param bitmap 原图片
	 * @param ratio 截取比例，如果是8，则圆角半径是宽高的1/8，如果是2，则是圆形图片
	 * @return 圆角矩形图片
	 */
	public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, float ratio)
	{
		Bitmap output = Bitmap.createBitmap(bitmap.getWidth(),
				bitmap.getHeight(), Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(output);

		final Paint paint = new Paint();
		final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
		final RectF rectF = new RectF(rect);

//		paint.setAntiAlias(true);
		canvas.drawARGB(0, 0, 0, 0);
		canvas.drawRoundRect(rectF, bitmap.getWidth()/ratio,
				bitmap.getHeight()/ratio, paint);

		paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
		canvas.drawBitmap(bitmap, rect, rect, paint);
		return output;
	}

	/**
	 * 将Bitmap图片转圆角。
	 *
	 * @param context
	 * @param bm
	 * @return
	 */
	public static Bitmap toRound(Context context, Bitmap bm)
	{
		Bitmap roundBm = null;
		if(bm != null)
		{
			try
			{
				roundBm = getRoundedCornerBitmap(bm, 2);
			}
			// 显式处理下OOM使得APP更健壮（OOM只能显式抓取，否则会按系统Error的方式报出从而使APP崩溃哦）
			catch (OutOfMemoryError e)
			{
				WidgetUtils.showToast(context, "处理图片变圆角时因内存不足而没有继续。", WidgetUtils.ToastType.WARN);

				Log.w(TAG, e);
			}
		}
		return roundBm;
	}

	/**
	 * 将指定文本输入组件中的字符数显示在另一个view上，用于实现实时输入字数功能。
	 *
	 * @param srcView 源输入组件
	 * @param shoutCountView 目的显示组件
	 */
	public static void setTextLengthCounter(TextView srcView, TextView shoutCountView){
		if(srcView != null && shoutCountView != null){
			srcView.addTextChangedListener(new TextWatcher() {
				@Override
				public void beforeTextChanged(CharSequence s, int start, int count, int after) {
				}

				@Override
				public void onTextChanged(CharSequence s, int start, int before, int count) {
				}

				@Override
				public void afterTextChanged(Editable s) {
					if(s != null && s.length() >0){
						shoutCountView.setText(String.valueOf(s.length()));
						return;
					}
					shoutCountView.setText("0");
				}
			});

			// 已输入字数的初始值显示
			int originalLength = 0;
			if(srcView.getText() != null)
				originalLength = srcView.getText().length();
			shoutCountView.setText(String.valueOf(originalLength));
		}
		else{
			Log.w(TAG, "无效的参考，srcView ="+srcView+"，shoutCountView="+shoutCountView);
		}
	}

	/**
	 * 代码里设置View组件的高度。
	 *
	 * @param v 要设置的组件对象
	 * @param height 高度（单位：像素）
	 */
	public static void setHeight (View v, int height)
	{
		if (v.getLayoutParams() instanceof ViewGroup.LayoutParams)
		{
			ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
			layoutParams.height = height;
		}
	}

    /**
     * 代码里设置View组件的margin。
     *
     * @param v 要设置的组件对象
     * @param left 左距（单位：像素）
     * @param top 上距（单位：像素）
     * @param right 右距（单位：像素）
     * @param bottom 下距（单位：像素）
     */
    public static void setMargins (View v, int left, int top, int right, int bottom)
    {
        if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams)
        {
            ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
            p.setMargins(left, top, right, bottom);
            v.requestLayout();
        }
    }
	
	public static void showWithDialog(Context context, String title, CharSequence msg)
	{
		new AlertDialog.Builder(context)
		.setTitle(title)  
		.setMessage(msg)
		.setNegativeButton(context.getResources().getString(R.string.general_ok), null)
		.show();  
	}

//	public static void setEditTextReadOnly(TextView view)
//	{
//		view.setTextColor(R.color.light_gray_for_text);   //设置只读时的文字颜色
//		if (view instanceof android.widget.EditText){
//			view.setCursorVisible(false);      //设置输入框中的光标不可见
//			view.setFocusable(false);           //无焦点
//			view.setFocusableInTouchMode(false);     //触摸时也得不到焦点
//		}
//	}

	/**
	 * <p>
	 * 将一个List<Map<String, Object>>样数据集中每一行的keyWillBeSum
	 * 指定单值进行合计，并返回合计结果.
	 * 
	 * <b>注：</b>本方法只对keyWillBeSum列是数字的情况下有意义！！
	 * </p>
	 * 
	 * @param datas 源数据集
	 * @param keyWillBeSum 目标列
	 */
	public static double sumColumn(List<Map<String, Object>> datas, String keyWillBeSum)
	{
		double sum = 0;
		//遍历该列的所有单元值并进行合计
		for(Map<String,Object> adapterData : datas)
			sum = DoubleHelper.add(sum, Double.valueOf(adapterData.get(keyWillBeSum).toString()));
		return sum;
	}

//	/**
//	 * 为View对象智能设置值.
//	 *
//	 * @param parentView 要进行值设定的View对象所在的父UI容器，因为需要通过它的方法 {@link View#findViewById(int)}来
//	 * 找到该View对象的实例引用（该实例应该是在诸如setContentView时被自动实例化的）
//	 * @param viewResId 要对其进行值设定的资源id
//	 * @param value 要设定的值，如果destView是TextView时则进行值设定时是调用value.toString()进行自动转换实现的
//	 * @see #setViewValue(View, Object)
//	 */
//	public static void setViewValue(View parentView,int viewResId,Object value)
//	{
//		setViewValue(parentView.findViewById(viewResId),value);
//	}
//	/**
//	 * <p>
//	 * 为View对象智能设置值.<br><br>
//	 *
//	 * 本方法目前只支持对TextView、Spinner及其所有直接和非直接子类的值设定——如果View对象是
//	 * TextView及其所有直接和非直接子类则对其调用.setText(value.toString())、如果View对象
//	 * 是Spinner及其所有直接和非直接子类则调用其Adapter的.setSelectedItem(..)进行值调定（
//	 * 前提是Spinner的Adapter对象必是RenderedSpinnerAdapter或其子类，因为它需要高台 用
//	 * RenderedSpinnerAdapter.setSelectedItem(..)进行值设定.）
//	 * </p>
//	 *
//	 * @param destView 要对其进行值设定的View对象
//	 * @param value 要设定的值，如果destView是TextView时则进行值设定时是调用value.toString()进行自动转换实现的
//	 */
//	public static void setViewValue(View destView,Object value)
//	{
//		//		View destView = findViewById(dataMode.getId());
//		if(destView instanceof TextView)//TextView及其所有直接和非直接子类
//			((TextView) destView).setText(String.valueOf(value));//value.toString());
//		else if(destView instanceof Spinner)
//		{
//			Adapter adp = ((Spinner) destView).getAdapter();
//			if(adp instanceof RenderedSpinnerAdapter)
//			{
//				RenderedSpinnerAdapter adapterList=(RenderedSpinnerAdapter)adp;
//				adapterList.setSelectedItem(value);
//			}
//			else
//			{
//				Log.w(TAG, "对Spinner对象进行自动设值时，要求它的Adapter必须是RenderedSpinnerAdapter或其子类，因为" +
//				"它需要高台 用RenderedSpinnerAdapter.setSelectedItem(..)进行值设定.");
//				return;
//			}
//		}
//		else
//			Log.w(TAG, "有一个View组件不支持，目前只支持对TextView、Spinner及其所有直接和非直接子类的值设定."+destView.getClass());
//	}

//	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 以下代码有待重构SSSSS
//	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 以下代码有待重构SSSSS
//	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 以下代码有待重构SSSSS
//	/**
//	 * 创建下拉框辅助类，简化创建下拉框的步骤
//	 * @param idnames
//	 * @param context
//	 * @param spinnerViewId
//	 * @return
//	 */
//	public static Spinner createRenderedSpinner(DataRender idnames,Context context,int spinnerViewId)
//	{
//		return createRenderedSpinner(idnames, context, spinnerViewId, true);
//	}
//	/**
//	 * 创建下拉框辅助类，简化创建下拉框的步骤 默认animate是true
//	 * @param idnames
//	 * @param context
//	 * @param spinnerViewId
//	 * @param event 初始化的时候是否触发监听器,false表示触发、true表示不触发
//	 * @return
//	 */
//	public static Spinner createRenderedSpinner(DataRender idnames,Context context,int spinnerViewId,boolean event)
//	{
//		Spinner spinner=(Spinner)((Activity)context).findViewById(spinnerViewId);
//		RenderedSpinnerAdapter adapter=new RenderedSpinnerAdapter(context,android.R.layout.simple_spinner_item,idnames,spinner);
//		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
//		spinner.setAdapter(adapter);
//		if(!event)
//			spinner.setSelection(0,true);
//		return spinner;
//	}
//
	/**
	 * 异步加载render并建立Spinner的实用例.
	 *
	 * <p>
	 * 异步加载render：Android自2.3及以后版后，要求网络交互必需要放在异步线程里处理！
	 * <p>
	 * 在2.3版本以后Android加入了StrictMode类，而在3.0在网络上能感觉到有更加严格的限制，更多的查询API上的StrictMode.
	 *
	 * @author Jack Jiang, 2013-09-23
	 * @version 1.0
	 */
	public static abstract class RenderedSpinnerCreatorAsync extends AsyncTask<Object, Integer, DataRender>
	{
		private Context activity = null;
		private Spinner spinner = null;
		private boolean event = true;

		public RenderedSpinnerCreatorAsync(Activity activity, int spinnerViewId)
		{
			this(activity, spinnerViewId, true);
		}
		public RenderedSpinnerCreatorAsync(Activity activity, int spinnerViewId, boolean event)
		{
			this(activity, (Spinner)activity.findViewById(spinnerViewId), event);
		}
		public RenderedSpinnerCreatorAsync(Context activity, Spinner spinner)
		{
			this(activity, spinner, true);
		}
		public RenderedSpinnerCreatorAsync(Context activity, Spinner spinner, boolean event)
		{
			this.activity = activity;
			this.spinner = spinner;
			this.event = event;
		}

//		/**
//		 * 处理耗时数据前先显示进度条.
//		 */
//		@Override
//		protected void onPreExecute()
//		{
//		}

		/**
		 * 在后台执行查询功能列表描述数据（不包括今日天气信息）.
		 *
		 * @param parems 参数没有意义
		 * @return 查询结果，将传递给onPostExecute(..)方法
		 */
		@Override
		protected DataRender doInBackground(Object... parems)
		{
			return fetchDataRender();
		}

		/** 从网络加载render数据的实现方法 */
		protected abstract DataRender fetchDataRender();

		/**
		 * <p>
		 * 用于处理queryData返回结果，并取消进度条的显示.<br>
		 * 最终的数据结果处理将交由方法 onPostExecute(Object) 处理.
		 * </p>
		 *
		 * @param render
		 */
		@Override
		protected void onPostExecute(DataRender render)
		{
			RenderedSpinnerAdapter adapter=new RenderedSpinnerAdapter(activity
					, android.R.layout.simple_spinner_item, render, spinner);
			adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
			spinner.setAdapter(adapter);
			if(!event)
				spinner.setSelection(0,true);
		}
	}
//	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 以下代码有待重构EEEEE
//	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 以下代码有待重构EEEEE
//	//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 以下代码有待重构EEEEE


	public static void areYouSure(Context context,
			java.lang.Object infoText,final Action okAction)
	{
		areYouSure(context,infoText,"操作确认",okAction,null);
	}
	public static void areYouSure(Context context,
			java.lang.Object infoText,final Action okAction, final Action cancelAction)
	{
		areYouSure(context,infoText,"操作确认",okAction,cancelAction);
	}
	public static void areYouSure(Context context,
			java.lang.Object infoText,
			java.lang.String title,
			final Action okAction,
			final Action cancelAction
	)
	{
		AlertDialog dlg = new AlertDialog.Builder(context)
		.setTitle(title)
		.setMessage(infoText+"")
		.setPositiveButton(context.getResources().getString(R.string.general_ok), new DialogInterface.OnClickListener(){
			@Override
			public void onClick(DialogInterface dialog, int which){
				if(okAction!=null)
					okAction.actionPerformed(dialog);
				dialog.dismiss();
			}
		})
		.setNegativeButton(context.getResources().getString(R.string.general_cancel), new DialogInterface.OnClickListener(){
			@Override
			public void onClick(DialogInterface dialog, int which){
				if(cancelAction!=null)
					cancelAction.actionPerformed(dialog);
				dialog.dismiss();
			}
		})
//		.setIcon(R.drawable.lib_comfirm)
		.create();
		dlg.setCanceledOnTouchOutside(false);
		dlg.show();
	}



	/**
	 * 显示一个Toast的实用方法（默认duration是  {@link Toast#LENGTH_SHORT} ）.
	 * 
	 * @param context he context to use. Usually your Application or Activity object.
	 * @param text 必须是Integer(包括int原始类型)和CharSequence及各自子类的实例
	 * @return
	 * @see #showToast(Context, Object, ToastType)
	 */
	public static <T> Toast showToast(Context context, T text)
	{
		return showToast(context, text, ToastType.NONE);
	}
	/**
	 * 显示一个Toast的实用方法（默认duration是  {@link Toast#LENGTH_SHORT} ）.
	 * 
	 * @param context he context to use. Usually your Application or Activity object.
	 * @param text 必须是Integer(包括int原始类型)和CharSequence及各自子类的实例
	 * @return
	 * @see #showToast(Context, Object, int, ToastType)
	 */
	public static <T> Toast showToast(Context context, T text,ToastType toastType)
	{
		return showToast(context, text, Toast.LENGTH_SHORT, toastType);
	}
	/**
	 * 显示一个Toast的实用方法（默认duration是  {@link Toast#LENGTH_LONG} ）..
	 * 
	 * @param context he context to use. Usually your Application or Activity object.
	 * @param text 必须是Integer(包括int原始类型)和CharSequence及各自子类的实例
	 * @return
	 * @see #showToastLong(Context, Object, ToastType)
	 */
	public static <T> Toast showToastLong(Context context, T text)
	{
		return showToastLong(context, text, ToastType.NONE);
	}
	/**
	 * 显示一个Toast的实用方法（默认duration是  {@link Toast#LENGTH_LONG} ）..
	 * 
	 * @param context he context to use. Usually your Application or Activity object.
	 * @param text 必须是Integer(包括int原始类型)和CharSequence及各自子类的实例
	 * @return
	 * @see #showToast(Context, Object, int, ToastType)
	 */
	public static <T> Toast showToastLong(Context context, T text,ToastType toastType)
	{
		return showToast(context, text, Toast.LENGTH_LONG, toastType);
	}
	/**
	 * <p>
	 * 显示一个Toast的实用方法.<br><br>
	 * 	<ul>
	 * 		<li>当text是CharSequence及其子类的对象时，本方法相当于调用{@link Toast#makeText(Context, CharSequence, int)}；</li>
	 * 		<li>当text是Integer及其子类的对象时，本方法相当于调用{@link Toast#makeText(Context, int, int)}；</li>
	 * 	</ui>
	 * </p>
	 * 
	 * @param context he context to use. Usually your Application or Activity object.
	 * @param text 必须是Integer(包括int原始类型)和CharSequence及各自子类的实例
	 * @param duration How long to display the message. Either LENGTH_SHORT or LENGTH_LONG
	 * @return
	 * @see Toast#makeText(Context, CharSequence, int)
	 * @see Toast#makeText(Context, int, int)
	 */
	public static <T> Toast showToast(Context context, T text, int duration
			,ToastType toastType)
	{
		if(toastType == ToastType.NONE && ((toastTypeSurport & TOAST_TYPE_NONE) != TOAST_TYPE_NONE))
		{
			Log.v("showToast", ""+text);
			return Toast.makeText(context, ""+text, duration); // 此时返回的toast没有意义，只是为了保证在此判断逻辑下返回的Toast不为null而已
		}
		if(toastType == ToastType.OK && ((toastTypeSurport & TOAST_TYPE_OK) != TOAST_TYPE_OK))
		{
			Log.i("showToast", ""+text);
			return Toast.makeText(context, ""+text, duration); // 此时返回的toast没有意义，只是为了保证在此判断逻辑下返回的Toast不为null而已
		}
		if(toastType == ToastType.INFO && ((toastTypeSurport & TOAST_TYPE_INFO) != TOAST_TYPE_INFO))
		{
			Log.v("showToast", ""+text);
			return Toast.makeText(context, ""+text, duration); // 此时返回的toast没有意义，只是为了保证在此判断逻辑下返回的Toast不为null而已
		}
		if(toastType == ToastType.WARN && ((toastTypeSurport & TOAST_TYPE_WARN) != TOAST_TYPE_WARN))
		{
			Log.w("showToast", ""+text);
			return Toast.makeText(context, ""+text, duration); // 此时返回的toast没有意义，只是为了保证在此判断逻辑下返回的Toast不为null而已
		}
		if(toastType == ToastType.ERROR && ((toastTypeSurport & TOAST_TYPE_ERROR) != TOAST_TYPE_ERROR))
		{
			Log.v("showToast", ""+text);
			return Toast.makeText(context, ""+text, duration); // 此时返回的toast没有意义，只是为了保证在此判断逻辑下返回的Toast不为null而已
		}

		// 按Toast信息类型显示对应的图标
		int imageResId = R.drawable.widget_toast_icon_info;
		switch(toastType)
		{
			case OK:
				imageResId = R.drawable.widget_toast_icon_ok;
				break;
			case INFO:
				imageResId = R.drawable.widget_toast_icon_info;
				break;
			case WARN:
				imageResId = R.drawable.widget_toast_icon_warn;
				break;
			case ERROR:
				imageResId = R.drawable.widget_toast_icon_error;
				break;
		}

		//******** 自Andriod 11开始，系统已明确禁止通过toast.getView()的方式自定义Toast，所以之前的代码本次将被注释掉停止使用！！
//		Toast toast = null;
//		if(text instanceof CharSequence)
//			toast = Toast.makeText(context, (CharSequence)text, duration);
//		else if(text instanceof Integer)
//			toast = Toast.makeText(context, (Integer) text, duration);
//		else
//			throw new IllegalArgumentException(
//					"无效参数,text不是CharSequence和Integer及各自子类的实例,text.getClass="+text.getClass());
//
//		if(toast!=null)
//		{
//			// Andriod 11及以上系统已明确禁止自定Toast，所以此处需判断只能在11以及的版本中使用
//			if(Build.VERSION.SDK_INT < Build.VERSION_CODES.R && toastType != ToastType.NONE)
//			{
//				LinearLayout toastView = (LinearLayout) toast.getView();
//				toastView.setOrientation(LinearLayout.HORIZONTAL);
//				ImageView imageCodeProject = new ImageView(context);
////				int imageResId = R.drawable.widget_toast_icon_info;
////
////				switch(toastType)
////				{
////					case OK:
////						imageResId = R.drawable.widget_toast_icon_ok;
////						break;
////					case INFO:
////						imageResId = R.drawable.widget_toast_icon_info;
////						break;
////					case WARN:
////						imageResId = R.drawable.widget_toast_icon_warn;
////						break;
////					case ERROR:
////						imageResId = R.drawable.widget_toast_icon_error;
////						break;
////				}
//
//				imageCodeProject.setImageResource(imageResId);
//				toastView.addView(imageCodeProject, 0);
//
//				// 增加衬距
//				LinearLayout.LayoutParams lp = (LayoutParams) imageCodeProject.getLayoutParams();
//		        lp.setMargins(0, 0, 15, 0);
//		        imageCodeProject.setLayoutParams(lp);
//			}
//
//			toast.show();
//		}


		//******** 为了支持包括Andriod 11在内的所有系统显示自定义Toast，以下代码将使用自定义layout的方式实现：

		// 获取LayoutInflater对象
		LayoutInflater inflater = LayoutInflater.from(context);
		// 父布局View对象
		View layout = inflater.inflate(R.layout.common_small_toast, null);

		// 文本控件
		TextView textView = layout.findViewById(R.id.common_small_toast_text);
		if(text instanceof CharSequence)
			textView.setText((CharSequence)text);
		else if(text instanceof Integer)
			textView.setText((Integer) text);
		else
			throw new IllegalArgumentException(
					"无效参数,text不是CharSequence和Integer及各自子类的实例,text.getClass="+text.getClass());

		// 图标控件
		ImageView iconView = layout.findViewById(R.id.common_small_toast_icon);

		Drawable sexImg = context.getResources().getDrawable(imageResId);
		iconView.setImageDrawable(sexImg);

		Toast toast = new Toast(context);
		// 设置Toast的位置
		toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
		toast.setDuration(duration);
		// 让Toast显示为我们自定义的样子
		toast.setView(layout);
		toast.show();

		return toast;
	}

	/**
	 * 自定义Toast类型.
	 */
	public enum ToastType
	{
		/** 使用系统默认样式 */
		NONE,
		/** 在toast左右增加了Ok图标样式的toast */
		OK,
		/** 在toast左右增加了Info图标样式的toast */
		INFO,
		/** 在toast左右增加了Warn图标样式的toast */
		WARN,
		/** 在toast左右增加了Error图标样式的toast */
		ERROR
	}
}
